using System;

namespace MatrixFramework.Shared.Application.Caching
{
    /// <summary>
    /// 缓存特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class CacheAttribute : Attribute
    {
        /// <summary>
        /// 缓存键前缀
        /// </summary>
        public string KeyPrefix { get; set; } = string.Empty;

        /// <summary>
        /// 缓存过期时间（分钟）
        /// </summary>
        public int ExpirationMinutes { get; set; } = 30;

        /// <summary>
        /// 是否启用缓存
        /// </summary>
        public bool Enabled { get; set; } = true;

        /// <summary>
        /// 是否根据用户ID区分缓存
        /// </summary>
        public bool PerUser { get; set; } = false;

        /// <summary>
        /// 是否根据租户ID区分缓存
        /// </summary>
        public bool PerTenant { get; set; } = false;

        /// <summary>
        /// 缓存键参数索引（从方法参数中选择）
        /// </summary>
        public int[] KeyParamIndexes { get; set; } = Array.Empty<int>();

        /// <summary>
        /// 缓存组名称（用于批量清理）
        /// </summary>
        public string? GroupName { get; set; }

        /// <summary>
        /// 条件缓存（当条件为true时才缓存）
        /// </summary>
        public string? Condition { get; set; }

        /// <summary>
        /// 除非条件为true，否则不缓存
        /// </summary>
        public string? Unless { get; set; }

        public CacheAttribute()
        {
        }

        public CacheAttribute(string keyPrefix, int expirationMinutes = 30)
        {
            KeyPrefix = keyPrefix;
            ExpirationMinutes = expirationMinutes;
        }

        public CacheAttribute(int expirationMinutes)
        {
            ExpirationMinutes = expirationMinutes;
        }
    }

    /// <summary>
    /// 缓存失效特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
    public class CacheEvictAttribute : Attribute
    {
        /// <summary>
        /// 要失效的缓存键
        /// </summary>
        public string[] CacheKeys { get; set; } = Array.Empty<string>();

        /// <summary>
        /// 要失效的缓存键前缀
        /// </summary>
        public string[] CacheKeyPrefixes { get; set; } = Array.Empty<string>();

        /// <summary>
        /// 是否失效所有缓存
        /// </summary>
        public bool AllEntries { get; set; } = false;

        /// <summary>
        /// 是否在方法执行前失效缓存
        /// </summary>
        public bool BeforeInvocation { get; set; } = false;

        /// <summary>
        /// 缓存组名称（失效该组下的所有缓存）
        /// </summary>
        public string? GroupName { get; set; }

        /// <summary>
        /// 缓存键参数索引（从方法参数中选择）
        /// </summary>
        public int[] KeyParamIndexes { get; set; } = Array.Empty<int>();

        /// <summary>
        /// 缓存键模式（用于模式匹配失效）
        /// </summary>
        public string? KeyPattern { get; set; }

        public CacheEvictAttribute()
        {
        }

        public CacheEvictAttribute(params string[] cacheKeys)
        {
            CacheKeys = cacheKeys;
        }

        public CacheEvictAttribute(string cacheKey)
        {
            CacheKeys = new[] { cacheKey };
        }
    }

    /// <summary>
    /// 缓存更新特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class CachePutAttribute : Attribute
    {
        /// <summary>
        /// 缓存键前缀
        /// </summary>
        public string KeyPrefix { get; set; } = string.Empty;

        /// <summary>
        /// 缓存过期时间（分钟）
        /// </summary>
        public int ExpirationMinutes { get; set; } = 30;

        /// <summary>
        /// 是否启用缓存
        /// </summary>
        public bool Enabled { get; set; } = true;

        /// <summary>
        /// 缓存键参数索引（从方法参数中选择）
        /// </summary>
        public int[] KeyParamIndexes { get; set; } = Array.Empty<int>();

        /// <summary>
        /// 缓存组名称
        /// </summary>
        public string? GroupName { get; set; }

        /// <summary>
        /// 条件缓存（当条件为true时才缓存）
        /// </summary>
        public string? Condition { get; set; }

        /// <summary>
        /// 除非条件为true，否则不缓存
        /// </summary>
        public string? Unless { get; set; }

        public CachePutAttribute()
        {
        }

        public CachePutAttribute(string keyPrefix, int expirationMinutes = 30)
        {
            KeyPrefix = keyPrefix;
            ExpirationMinutes = expirationMinutes;
        }
    }
}